package org.midy.infrastructure;

import org.midy.infrastructure.tools.CloseHandler;
import org.midy.infrastructure.tools.Logger;

import java.nio.channels.SelectionKey;
import java.nio.channels.SocketChannel;

public class ConnectEventHandler implements EventHandler {

    private final EventDrivenTaskAllocation eventDrivenTaskAllocation;

    public ConnectEventHandler(EventDrivenTaskAllocation eventDrivenTaskAllocation) {
        this.eventDrivenTaskAllocation = eventDrivenTaskAllocation;
    }

    /**
     * 一共有3个场景：
     *   场景1：建立连接成功，socketChannel.isConnected() == true
     *      注；需要取消掉监听连接的SelectionKey
     *   场景2：连接正在建立中(没有成功，但是仍在建立连接中), socketChannel.isConnected() == false && socketChannel.isConnectionPending() == true
     *      注：继续监听处理
     *   场景3：连接没有建立成功，也没有在建立中时，默认做失败处理
     *      注；需要取消掉监听连接的SelectionKey
     *
     * @param selectionKey  当前事件关注的时间类型
     * @return  无效返回值
     */
    @Override
    public Object handle(SelectionKey selectionKey) {
        if (selectionKey.isValid()) {
            SocketChannel socketChannel = null;
            try {
                socketChannel = (SocketChannel) selectionKey.channel();
                if (socketChannel.isConnected()) {
                    boolean allocation = eventDrivenTaskAllocation.allocation(socketChannel, SelectionKey.OP_READ);
                    if (allocation) {
                        Logger.info("[新连接] IP:PORT[%s], 分派成功!" + socketChannel.getRemoteAddress().toString());
                    } else {
                        Logger.info("[新连接] IP:PORT[%s], 分派失败" + socketChannel.getRemoteAddress().toString());
                        if (socketChannel.isOpen()) {
                            CloseHandler.closeSocketChannel(socketChannel);
                        }
                    }
                    selectionKey.cancel();
                } else if (socketChannel.isConnectionPending()) {
                    socketChannel.register(selectionKey.selector(), SelectionKey.OP_CONNECT);
                    Logger.info("[新连接] IP:PORT[%s], 正在连接中 ... ", socketChannel.getRemoteAddress().toString());
                } else {
                    Logger.info("[新连接] IP:PORT[%s], 连接失败",socketChannel.getRemoteAddress().toString());
                    selectionKey.cancel();
                    CloseHandler.closeSocketChannel(socketChannel);
                }
            } catch (Throwable t) {
                Logger.error("等待连接完成失败！", t);
                selectionKey.cancel();
                CloseHandler.closeSocketChannel(socketChannel);
            }
        }
        return false;
    }
}
